#include "intArray_t.h"
#include <iostream>
using namespace std;

intArray_t::intArray_t() :
	expandValue(16) {
	numElements = 0;
	capacity = expandValue;
	arr = new int*[capacity];
	zeroArray();
}

intArray_t::intArray_t(const int initialSize) :
	expandValue(16) {
	numElements = 0;
	capacity = initialSize;
	arr = new int*[capacity];

}
intArray_t::~intArray_t() {
	delete[] arr;
}

int intArray_t::getNumberOfElements() const {
	return numElements;
}

int intArray_t::getExpandValue() const {
	return expandValue;
}

int intArray_t::getCapacity() const {
	return capacity;
}

int* intArray_t::getFirstElement() const {
	if (numElements == 0) {
		return 0;
	}
	return arr[0];
}

int* intArray_t::getLastElement() const {
	if (numElements == 0) {
		return 0;
	}
	return arr[numElements - 1];
}

int* intArray_t::find(int val) const {
	int fIndex = findIndex(val, 0);
	return (fIndex == -1) ? 0 : arr[fIndex];
}

int* intArray_t::remove(int val) {
	int fIndex = findIndex(val, 0);
	
	int* ret = 0;

	if (fIndex != -1) {
		ret = arr[fIndex];
		removeIndex(fIndex);
	}
	
	return ret;
}

void intArray_t::removeAll() {
	for (int i = 0; i < numElements; i++) {
		arr[i] = 0;
	}
	numElements = 0;
}

void intArray_t::removeDelete(int val) {
	int fIndex = findIndex(val, 0);

	while (fIndex != -1) {
		delete arr[fIndex];
		removeIndex(fIndex);

		fIndex = findIndex(val, fIndex);
	}

}

void intArray_t::removeDeleteAll() {
	for (int i = 0; i < numElements; i++) {
		delete arr[i];
		arr[i] = 0;
	}
	numElements = 0;
}

void intArray_t::insert(int* const newElem) {
	append(numElements - 1, newElem);
}

int intArray_t::append(int index, int* const newElem) {
	if ((index > numElements - 1) || (index < -1)) {
		return 0;
	}

	if (numElements == capacity) {
		expandArray();
	}

	int i = 0;
	for (i = numElements; i > index + 1; i--) {
		arr[i] = arr[i - 1];
	}
	arr[i] = newElem;

	numElements++;

	return 1;
}

int intArray_t::prepend(int index, int* const newElem) {
	return append(index - 1, newElem);
}

void intArray_t::printAll() {
	int i = 0;

	cout << "Printing array of size " << numElements << "(" << "out of " << capacity << ", expand=" << expandValue << "):" << "\n";
	for (i = 0; i < numElements; i++) {
		cout << "\t" << i << ": " << arr[i] << "(value: " << *arr[i] << ")" << "\n";
	}
	for (i = numElements; i < capacity; i++) {
		cout << "\t" << i << ": " << arr[i] << "\n";
	}
}

bool intArray_t::isEmpty() {
	return (numElements == 0);	
}

/* Private functions */

int intArray_t::findIndex(int val, int startFrom) const {
	for (int i = startFrom; i < numElements; i++) {
		if (*(arr[i]) == val) {
			return i;
		}
	}
	return -1;
}

void intArray_t::removeIndex(int fIndex) {
	int i;

	// Move all elements back
	for (i = fIndex; i < numElements - 1; i++) {
		arr[i] = arr[i + 1];
	}
	arr[i] = 0;

	// Lower number of elements in array
	numElements--;
}

void intArray_t::expandArray() {
	int** oldArr = arr;
	int oldNumElements = numElements;

	capacity += expandValue;
	arr = new int*[capacity];
	zeroArray();

	for (int i = 0; i < oldNumElements; i++) {
		arr[i] = oldArr[i];
	}
	numElements = oldNumElements;

	delete[] oldArr;
}

void intArray_t::zeroArray() {
	for (int i = 0; i < capacity; i++) {
		arr[i] = 0;
	}
	numElements = 0;
}

